home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
076-100
/
scopedisk83
/
popcli4
/
popparse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-19
|
10KB
|
351 lines
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1986 The Software Distillery. All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of */
/* | . | || the authors. */
/* | o | || Dave Baker Ed Burnette Stan Chow Jay Denebeim */
/* | . |// Gordon Keener Jack Rouse John Toebes Doug Walker */
/* ====== BBS:(919)-471-6436 VOICE:(919)-469-4210 */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* VERY loosely based on the input.device example by Rob Peck, 12/1/85
*/
#include "popcli.h"
#include "popbug.h"
/* KLUDGE: (sort of) These strings can ONLY be accessed if gptr->stdout */
/* is non-zero, since they *should* be in the PopCLI hunk that */
/* gets thrown away. */
#define CSI "\x9B"
#define HILIT CSI "0;33m"
#define BOLD CSI "1m"
#define PLAIN CSI "0m"
#define COPYR "\xA9"
char killmsg[] =
HILIT "PopCLI IV" PLAIN " Terminating\n";
char banner[] =
HILIT "PopCLI IV" PLAIN
" - Copyright " COPYR " 1987,1989 The Software Distillery\n"
" 235 Trillingham Lane, Cary NC 27513 BBS:(919)-471-6436\n";
char helpmsg[] =
"Usage:\n"
" " BOLD "POPCLI" PLAIN " [[secs | ADD | REPL] [key]] [[cmdmods] [CMD] cmnd]\n"
" " BOLD "POPCLI" PLAIN " FREE [key]\n"
" " BOLD "POPCLI" PLAIN " EXEC [key]\n"
" " BOLD "POPCLI" PLAIN " BLANK\n"
" " BOLD "POPCLI" PLAIN " UNBLANK\n"
" " BOLD "POPCLI" PLAIN " TIME n\n"
" " BOLD "POPCLI" PLAIN " QUIT\n"
" cmdmods: [NOWB] [MINMEM n] [MINCHIP n]\n"
"where:\n"
" secs is the number of seconds before blanking screen\n"
" key is the scan code for the key to press with Left Amiga\n"
" <decimal>, 0x<hex>, F{1-10}, DEL, ESC, or 'c',\n"
" where c is any ASCII character from ' ' to '~'\n"
" ADD Activates Left Amiga-<key> without altering the blanking time\n"
" REPL Same as ADD, but more mnemonic for redefining a key\n"
" NOWB don't bring the workbench screen to front before executing command\n"
" MINMEM Make sure at least n bytes are available before executing command\n"
" MINCHIP Like MINMEM, but checks for chip memory only.\n"
" CMD Optional tag, in case command starts with a keyword or number\n"
" cmnd is to be executed when Left Amiga-<key> is pressed\n"
" FREE Deactivates Left Amiga-<key>, but leaves POPCLI up\n"
" EXEC Executes the given key\n"
" BLANK Blanks the screen immediately\n"
" UNBLANK Unblanks the screen, resetting the timer countdown\n"
" TIME Sets the timeout value without clobbering any key definitions\n"
" QUIT Brings down POPCLI and all command keys.\n"
"\n"
"From ARexx: ADDRESS POPCLI4 <popcli-arguments>\n";
/* Make this a multiple of 2 bytes long!!! */
struct KEYWORD {
char name[8];
char command;
char wherenum;
};
#define KW_QUIT 0
#define KW_NOWB 1
#define KW_CMD 2
#define KW_ESC 3
#define KW_DEL 4
#define KW_ADD 5
#define KW_REPL 6
#define KW_FREE 7
#define KW_TIME 8
#define KW_MEM 9
#define KW_CHIP 10
#define KW_EXEC 11
#define KW_BLNK 12
#define KW_UNBL 13
#define NUM_NONE 0
#define NUM_KEY 1
#define NUM_TIME 2
#define NUM_MEM -1
#define NUM_CHIP -2
#define ISMEMNUM(n) (n < 0)
#ifdef CONST_KLUDGE
#define PARSETBL_KLUDGE \
"quit\0\0\0\0" "\04" "\01" \
"nowb\0\0\0\0" "\00" "\01" \
"cmd\0\0\0\0\0" "\00" "\01" \
"esc\0\0\0\0\0" "\00" "\01" \
"del\0\0\0\0\0" "\00" "\01" \
"add\0\0\0\0\0" "\01" "\01" \
"repl\0\0\0\0" "\01" "\01" \
"free\0\0\0\0" "\02" "\01" \
"time\0\0\0\0" "\07" "\02" \
"minmem\0\0" "\00" "\xff" \
"minchip\0" "\00" "\xfe" \
"exec\0\0\0\0" "\03" "\01" \
"blank\0\0\0" "\05" "\01" \
"unblank\0" "\06" "\01" \
"\00" /* To ensure even alignment */
#define KW_MAX 14
#else
const struct KEYWORD parsetbl[] = {
{ "quit", MSG_SHUTDOWN, NUM_KEY },
{ "nowb", MSG_NONE, NUM_KEY },
{ "cmd", MSG_NONE, NUM_KEY },
{ "esc", MSG_NONE, NUM_KEY },
{ "del", MSG_NONE, NUM_KEY },
{ "add", MSG_ADDKEY, NUM_KEY },
{ "repl", MSG_ADDKEY, NUM_KEY },
{ "free", MSG_DELKEY, NUM_KEY },
{ "time", MSG_SETTIME, NUM_TIME },
{ "minmem", MSG_NONE, NUM_MEM },
{ "minchip", MSG_NONE, NUM_CHIP },
{ "exec", MSG_EXECUTE, NUM_KEY },
{ "blank", MSG_BLANK, NUM_KEY },
{ "unblank", MSG_UNBLANK, NUM_KEY }
};
#define KW_MAX ((sizeof(parsetbl))/(sizeof(struct KEYWORD)))
#endif
#define MAXKWLEN 8
#define KWCMP(a,b) ((*(long *)a) == (*(long *)b) && \
((long *)a)[1] == ((long *)b)[1])
/* SCODE table characters are in the following order: */
/* !"#$%&'()*+,-./ */
/* @ABCDEFGHIJKLMNO */
/* PQRSTUVWXYZ[\]^_ */
/* `abcdefghijklmno */
/* pqrstuvwxyz{|}~ */
#define SCODE \
"\x40\x01\x2a\x03\x04\x05\x07\x2a\x09\x0a\x08\x0c\x38\x0b\x39\x3a" \
"\x0a\x01\x02\x03\x04\x05\x06\x07\x08\x09\x29\x29\x38\x0b\x39\x3a" \
"\x02\x20\x35\x33\x22\x12\x23\x24\x25\x17\x26\x27\x28\x37\x36\x18" \
"\x19\x10\x13\x21\x14\x16\x34\x11\x32\x15\x31\x1a\x0d\x1b\x06\x0a" \
"\x00\x20\x35\x33\x22\x12\x23\x24\x25\x17\x26\x27\x28\x37\x36\x18" \
"\x19\x10\x13\x21\x14\x16\x34\x11\x32\x15\x31\x1a\x0d\x1b\x00\x46"
static void WriteOut( GLOBAL_DATA *, char *, int );
void popbanner( gptr )
GLOBAL_DATA *gptr;
{
WriteOut( gptr, banner, sizeof(banner)-1 );
}
void poptrailer( gptr )
GLOBAL_DATA *gptr;
{
WriteOut( gptr, killmsg, sizeof(killmsg)-1 );
}
int popparse( gptr, cmd, msg )
GLOBAL_DATA *gptr;
register char *cmd;
register struct OURMSG *msg;
{
long buff[MAXKWLEN/sizeof(long)+1];
char *p, *q;
int kw;
int len;
int value;
char wherenum;
#ifdef CONST_KLUDGE
struct KEYWORD *parsetbl = (struct KEYWORD *)PARSETBL_KLUDGE;
#endif
msg->type = MSG_ADDKEY;
msg->interval = 0;
msg->key = DEFKEY;
msg->minmem = 0;
msg->minchip = 0;
strcpy( msg->command, DEFCMD );
msg->cmdflags = 0;
wherenum = NUM_TIME;
/* if we were run from CLI then output our banner and process parameters */
if (!cmd)
return( OK );
if (*cmd == '?')
{
WriteOut(gptr, helpmsg, sizeof(helpmsg)-1);
return( LEAVE );
}
while( *cmd )
{
while (*cmd && *cmd <= ' ') cmd++;
/* Fetch the next keyword into a temp. buffer, lowercasing */
buff[0] = buff[1] = 0;
for (p = cmd, q = (char *)buff; *p > ' '; *q++ = (*p++ | ' '))
{
/* Too long to be a keyword... */
if (q >= ((char *)buff)+MAXKWLEN)
goto gotacmd;
}
for (kw = 0; kw < KW_MAX; kw++)
{
if (KWCMP(parsetbl[kw].name, buff))
{
/* We found a valid keyword! */
wherenum = parsetbl[kw].wherenum;
if (parsetbl[kw].command != MSG_NONE)
msg->type = parsetbl[kw].command;
switch( kw ) {
case KW_QUIT:
return(SHUTDOWN);
break;
case KW_NOWB:
msg->cmdflags |= FLAG_NOWB2F;
break;
case KW_CMD:
/* Skip intervening blanks, then treat as a command */
for (cmd = p; *cmd && *cmd == ' '; cmd++);
goto gotacmd;
break;
case KW_ESC:
msg->key = 0x45;
break;
case KW_DEL:
msg->key = 0x46;
break;
/* These are all handled by the table code!! */
/* NOTE: I have arranged the parse table such that all */
/* of these have larger values than the keywords which */
/* actually *do* something here. I have to comment out */
/* the case labels, though, because the compiler would */
/* put them in the jump table anyway. */
/* case KW_ADD: */
/* case KW_REPL: */
/* case KW_FREE: */
/* case KW_TIME: */
/* case KW_MEM: */
/* case KW_CHIP: */
/* case KW_EXEC: */
/* case KW_BLNK: */
/* case KW_UNBL: */
default:
break;
}
goto kwdone;
}
}
/* No keywords found; must be a key, number, or command */
if (*((char *)buff) == 'f')
{
/* User possibly typed F1-F10, but if not, we don't */
/* want to complain, just get the command */
len = stcd_i( ((char *)buff)+1, &value ) + 1;
if (((char *)buff)[len] || (value < 1) || (value > 10))
/* Treat it as a command */
goto gotacmd;
else
{
wherenum = NUM_KEY;
value += 0x4f; /* Translate to scan code */
}
}
else if (*((short *)buff) == 0x3078) /* "0x" */
{
/* Number is in hex, rather than decimal */
len = stch_i( ((char *)buff)+2, &value ) + 2;
}
else if (*((char *)buff) == '\'') /* ' */
{
/* Number is an actual key picture */
value = SCODE[(((char *)buff)[1] & 0x7f)-' '];
len = 3;
}
else
len = stcd_i( (char *)buff, &value );
/* Make sure we got a valid value. If not, must be a */
/* start of a command. */
if (((char *)buff)[len])
{
goto gotacmd; /* Leaves the function */
}
if (value && ISMEMNUM(wherenum))
{
value = ((value >> 10) + 1);
if (wherenum == NUM_MEM)
msg->minmem = value;
else
msg->minchip = value;
}
else if (wherenum == NUM_TIME)
msg->interval = value;
else
msg->key = value;
kwdone:
cmd = p;
}
gotacmd:
if (*cmd)
{
strncpy( msg->command, cmd, MAXCMD-1 );
msg->command[MAXCMD-1] = '\0';
}
return(OK);
}
static void WriteOut( gptr, msg, len )
GLOBAL_DATA *gptr;
char *msg;
int len;
{
if (gptr->stdout)
Write( gptr->stdout, msg, len );
}